import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class CloudFileClient {
    private int port = 8888;    //端口号
    private String ip;    //IP 地址
    private Socket socket = null;
    private Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        //启动客户端
        new CloudFileClient().startAPP();
    }

    private void startAPP() {
        try {
            System.out.print("请输入网盘 IP 地址: ");
            //获取网盘的 IP 地址
            ip = sc.next();
            while (true) {
                //根据服务端地址和端口号创建 Socket 对象
                socket = new Socket(ip, port);
                System.out.println("---黑马网盘---");
                System.out.println("1.查看可下载清单 2.上传文件 3.下载文件");
                System.out.print("输入操作编号: ");
                int num = sc.nextInt();
                switch (num) {
                    case 1:
                        //获取文件列表
                        getFiles();
                        break;
                    case 2:
                        //上传文件
                        updateFile();
                        break;
                    case 3:
                        //下载文件
                        downloadFile();
                        break;
                    default:
                        System.out.println("输入操作编号有误，请重新输入！");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("无法连接至服务器，请检查输入的IP地址！");
        }
    }

    /**
     * 获取文件列表
     */
    private void getFiles() throws Exception {
        //创建输出流对象
        DataOutputStream netOut = new DataOutputStream(socket.getOutputStream());
        //向服务器端发送表示当前操作的标记，1表示当前为获取文件列表
        netOut.writeUTF("1");
        //创建输入流对象
        DataInputStream netIn = new DataInputStream(socket.getInputStream());
        //读取响应回来的内容
        String msg = netIn.readUTF();
        //将文件列表根据符号|进行分隔，逐个输出
        String[] fileNameArray = msg.split("\\|");
        System.out.println("---当前可下载的文件---");
        for (String str : fileNameArray) {
            System.out.println(str);
        }
    }

    /**
     * 上传文件
     */
    private void updateFile() throws Exception {
        System.out.print("请输入需要上传的文件路径（含文件名）：");
        //获取输入的文件路径
        String f = sc.next();
        //创建上传文件对应的File对象
        File file = new File(f);
        //如果文件不存在，或者不是文件
        if (!file.exists() || !file.isFile()) {
            System.out.println("文件无效，请重写输入文件！");
            return;
        }
        //获取文件大小，这里限制文件大小必须在 64k 以下 (65536 字节)
        if (file.length() > 65536) {
            System.out.println("文件超过了 64KB! ");
            return;
        }

        //创建输出流对象
        DataOutputStream netOut = new DataOutputStream(socket.getOutputStream());
        //拼接上传操作标记和文件名称
        String sendMsg = "2" + file.getName();
        //将上传操作标记和文件名称发送到服务器端
        netOut.writeUTF(sendMsg);
        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] buffer = new byte[1024];
        int len;
        //将本地文件写入到流中发送到服务器端
        while ((len = fileInputStream.read(buffer)) != -1) {
            netOut.write(buffer, 0, len);
        }
        socket.shutdownOutput();
        DataInputStream netIn = new DataInputStream(socket.getInputStream());
        //获取上传结果
        System.out.println(netIn.readUTF());
        netIn.close();
        netOut.close();
    }

    /**
     * 下载文件
     */
    private void downloadFile() throws Exception {
        System.out.print("请输入需要下载的文件和下载的目标路径," +
                "目标路径不含文件名（输入格式：下载文件名 | 下载目标路径）: ");
        //获取控制台输入内容
        String file = sc.next();
        String[] split = file.split("\\|");
        String filename = split[0];
        DataOutputStream netOut = new DataOutputStream(socket.getOutputStream());
        //将下载操作标记和文件名称发送到服务器端
        netOut.writeUTF("3" + filename);
        DataInputStream netIn = new DataInputStream(socket.getInputStream());
        //获取下载的响应标志
        String s = netIn.readUTF();
        //如果所下载的文件不在列表中
        if ("error".equals(s)) {
            System.out.println(netIn.readUTF());
        } else {
            FileOutputStream fileOutputStream = new FileOutputStream(
                    split[1] + "/" + filename);
            byte[] buffer = new byte[1024];
            int len;
            //将服务器端响应回的文件写到指定的文件中
            while ((len = netIn.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, len);
            }
            fileOutputStream.close();
            netIn.close();
            System.out.println("文件下载成功！");
        }
    }
}